import { createStore } from 'vuex'
import axios from './libs/axios'
import { arrToObj, objToArr } from './helper'

export interface ResponseType<T = Record<string, unknown>> {
  code: number;
  msg: string;
  data: T
}

export interface AvatarProps {
  _id?: string;
  url?: string;
  fitUrl?: string;
}

export interface ColumnProps {
  _id: string;
  title: string;
  avatar?: AvatarProps;
  description: string;
  createdAt: string;
}

export interface ImageProps {
  _id?: string;
  url?: string;
  fitUrl?: string;
}

export interface AuthorProps {
  _id: string;
  nickName: string;
  email: string;
  description: string;
  avatar?: AvatarProps;
}

export interface PostProps {
  author: string | AuthorProps;
  _id: string;
  title: string;
  content: string;
  image?: ImageProps;
  createdAt: string;
  column: string;
  excerpt: string;
  isHTML?: boolean;
}

export interface UserProps {
  isLogin: boolean;
  nickName?: string;
  _id?: string;
  column?: string;
  avatar?: AvatarProps;
  description?: string;
  email?: string;
}

export interface GlobalErrorProps {
  status: boolean;
  message?: string;
}

interface DataProps<T> {
  [key: string]: T
}

export interface GlobalDataProps {
  columns: DataProps<ColumnProps>;
  posts: DataProps<PostProps>;
  user: UserProps;
  loading: number;
  token: string;
  error: GlobalErrorProps;
}

export default createStore<GlobalDataProps>({
  state: {
    columns: {},
    posts: {},
    user: {
      isLogin: false
    },
    loading: 0,
    token: localStorage.getItem('token') || '',
    error: {
      status: false
    }
  },
  mutations: {
    login (state, rawData) {
      const { token } = rawData.data
      state.token = token
      localStorage.setItem('token', token)
      axios.defaults.headers.common.Authorization = `Bearer ${token}`
    },
    fetchColumns (state, rawData) {
      state.columns = {
        ...state.columns,
        ...arrToObj(rawData.data.list)
      }
    },
    clearColumns (state) {
      state.columns = {}
    },
    fetchColumn (state, rawData) {
      state.columns = arrToObj([rawData.data])
    },
    fetchPosts (state, rawData) {
      state.posts = {
        ...state.posts,
        ...arrToObj(rawData.data.list)
      }
    },
    clearPosts (state) {
      state.posts = {}
    },
    fetchPost (state, rawData) {
      state.posts = arrToObj([rawData.data])
    },
    addLoading (state) {
      state.loading++
    },
    delLoading (state) {
      state.loading--
    },
    fetchCurrentUser (state, rawData) {
      state.user = {
        isLogin: true,
        ...rawData.data
      }
    },
    setError (state, err: GlobalErrorProps) {
      state.error = err
    },
    logout (state) {
      state.token = ''
      localStorage.removeItem('token')
      delete axios.defaults.headers.common.Authorization
      state.user = {
        isLogin: false
      }
    }
  },
  actions: {
    fetchColumns (context, currentPage) {
      return axios({
        url: '/columns',
        params: {
          currentPage,
          pageSize: 6
        },
        method: 'get'
      }).then(res => {
        context.commit('fetchColumns', res.data)
        return res.data
      })
    },
    fetchColumn (context, cid: string) {
      axios({
        url: `/columns/${cid}`,
        method: 'get'
      }).then(res => {
        context.commit('fetchColumn', res.data)
      })
    },
    fetchPosts (context, params) {
      return axios({
        url: `/columns/${params.cid}/posts`,
        params: {
          currentPage: params.currentPage,
          pageSize: 5
        },
        method: 'get'
      }).then(res => {
        context.commit('fetchPosts', res.data)
        return res.data
      })
    },
    fetchPost (context, pid: string) {
      axios({
        url: `/posts/${pid}`,
        method: 'get'
      }).then(res => {
        context.commit('fetchPost', res.data)
      })
    },
    login (context, payload) {
      return axios({
        url: '/user/login',
        data: payload,
        method: 'post'
      }).then(res => {
        context.commit('login', res.data)
        return res.data
      })
    },
    fetchCurrentUser (context) {
      return axios({
        url: '/user/current',
        method: 'get'
      }).then(res => {
        context.commit('fetchCurrentUser', res.data)
      })
    },
    createPost (context, payload) {
      return axios({
        url: '/posts',
        data: payload,
        method: 'post'
      }).then(res => {
        return res.data
      })
    }
  },
  getters: {
    getColumns (state) {
      return objToArr(state.columns)
    },
    getColumnById (state) {
      return (_id: string) => {
        return state.columns[_id]
      }
    },
    getPostsByCid (state) {
      return (cid: string) => {
        return objToArr(state.posts).filter(post => {
          return post.column === cid
        })
      }
    },
    getPostById (state) {
      return (_id: string) => {
        return state.posts[_id]
      }
    }
  }
})
